﻿using System;

using System.Collections.Generic;
using System.Text;

namespace Silvermoon.Controls
{
    /// <summary>
    /// Generates and manages controls to display INavigation nodes.
    /// </summary>
    /// <typeparam name="I">Type of control to generate.</typeparam>
    public  class NavigationControlGenerator<C> : IDisposable where C : Control
    {
        private List<C> cachedControls = new List<C>();
        private NavigationBase provider;

        public void Dispose()
        {

            provider.GetControl -= OnGetControl;
            provider.ReleaseControl -= OnReleaseControlBase;
            provider.SelectedNode = null;
            foreach (Control c in cachedControls) c.Dispose();
            cachedControls.Clear();
        }

        public NavigationControlGenerator(NavigationBase provider)
            : base()
        {
            if (provider == null) throw new ArgumentNullException("provider");
            this.provider = provider;
            provider.GetControl += new EventHandler<NavigationEventArgs>(OnGetControl);
            provider.ReleaseControl += new EventHandler<NavigationEventArgs>(OnReleaseControlBase);
        }

        private void OnReleaseControlBase(object sender, NavigationEventArgs e)
        {
            C container = e.Control as C;
            cachedControls.Add(container);
            e.Control = null;
            OnReleaseControl(container, e.Navigation);
        }


        private void OnGetControl(object sender, NavigationEventArgs e)
        {
            int n = cachedControls.Count - 1;
            C container;
            if (n >= 0)
            {
                container = cachedControls[n];
                cachedControls.RemoveAt(n);
            }
            else
            {
                container = CreateInstance();
            }
            OnInitializeControl(container, e.Navigation);
            e.Control = container;
        }

        protected virtual void OnInitializeControl(C container, INavigationNode node)
        {

        }

        protected virtual C CreateInstance()
        {
            return Activator.CreateInstance<C>();
        }

        protected virtual void OnReleaseControl(C container, INavigationNode node)
        {
        }


    }
}
